extends Node


func set_mouse_center():
	var center = get_viewport().get_visible_rect().size / 2.0
	get_viewport().warp_mouse(center)
	

func set_mouse_position(position: Vector2):
	get_viewport().warp_mouse(position)


func generate_id() -> String:
	var base = str(Time.get_ticks_usec()) + str(randi())
	var h = hash(base) # 64位整数
	return String.num_int64(h, 16) # 输出 16进制字符串


func get_rand_dir_between_angle(start_angle: float, end_angle: float):
	var angle_deg = randf_range(start_angle, end_angle)
	var angle_rad = deg_to_rad(angle_deg)
	var direction = Vector2.RIGHT.rotated(angle_rad)
	return direction
	
	
func start_particle_emit(particle: GPUParticles2D):
	particle.restart()
	particle.emitting = true
	

func stop_particle_emit(particle: GPUParticles2D):
	particle.emitting = false


func tween_light_on(light: PointLight2D, max_energy: float, on_time: float):
	var tween = create_tween()
	tween.tween_property(light, "energy", max_energy, on_time) \
	.set_trans(Tween.TRANS_SINE) \
	.set_ease(Tween.EASE_OUT)
	

func tween_light_off(light_particle: GPUParticles2D, light: PointLight2D, off_time: float):
	var tween = create_tween()
	tween.tween_property(light, "energy", 0, off_time) \
	.set_trans(Tween.TRANS_SINE) \
	.set_ease(Tween.EASE_OUT)
	

func raycast_to(from: Vector2, to: Vector2, collision_layer_index: int) :
	var space: PhysicsDirectSpaceState2D = get_tree().root.world_2d.direct_space_state
	
	var params := PhysicsRayQueryParameters2D.create(from, to)
	params.collision_mask = 1 << (collision_layer_index - 1)   
	params.collide_with_areas = true
	params.collide_with_bodies = true
	params.hit_from_inside = true

	var result: Dictionary = space.intersect_ray(params)
	return result


func clamp_position_to_rects(pos: Vector2, rects: Array[Rect2]) -> Vector2:
	var inside_any = false
	var closest_point = pos
	var min_dist = INF
	
	for rect in rects:
		if rect.has_point(pos):
			# 如果点在某个 rect 内，直接返回该点
			return pos
		
		# 否则，计算该 rect 边界上距离 pos 最近的点
		var clamped = Vector2(
			clamp(pos.x, rect.position.x, rect.position.x + rect.size.x),
			clamp(pos.y, rect.position.y, rect.position.y + rect.size.y)
		)
		
		# 找出距离最近的矩形边界
		var dist = pos.distance_to(clamped)
		if dist < min_dist:
			min_dist = dist
			closest_point = clamped
	
	return closest_point


func is_point_in_rects(point: Vector2, rects: Array[Rect2]) -> bool:
	for rect in rects:
		if rect.has_point(point):
			return true
	return false


func born_unit(born_unit_data: UnitBaseData, position: Vector2):
	var unit_data = born_unit_data.duplicate(true) as UnitBaseData
	unit_data.max_hp = unit_data.config.base_life
	unit_data.hp = unit_data.max_hp
	unit_data.home_position = position
	unit_data.pos = position
	
	var level = get_tree().current_scene as Level
	level.level_data.units_data.append(unit_data)
	
	level.create_unit_by_unit_data(unit_data) 


func set_window_mode_fullscreen_borderless():
	if GlobalData.window_mode == 0: return
	
	GlobalData.window_mode = 0		
	DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
	DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
	DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
	DisplayServer.window_set_size(DisplayServer.screen_get_size())
	DisplayServer.window_set_position(Vector2.ZERO)


func set_window_mode_fullscreen():
	if GlobalData.window_mode == 1: return
	
	GlobalData.window_mode = 1		
	DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, false)
	DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED, false)
	DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)


func set_window_mode_windowed():
	if GlobalData.window_mode == 2: return
	
	GlobalData.window_mode = 2
	DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, false)
	DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED, true)
	DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
	DisplayServer.window_set_size(Vector2(1280, 720))
	DisplayServer.window_set_position((DisplayServer.screen_get_size() - DisplayServer.window_get_size()) / 2)
